// -----------------------------------------------------------------------
// <copyright file="GameManager.cs" company="x">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace BeatEmUp
{
    using BeatEmUp.Characters.Enemies;
    using BeatEmUp.Enums;
    using BeatEmUp.HUD;
    using BeatEmUp.Items;
    using BeatEmUp.Items.Weapons;
    using BeatEmUp.Menu;
    using BeatEmUp.World.Drawable;
    using BeatEmUp.World;
    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;
    using Microsoft.Xna.Framework.Input;
    using System;
    using System.Collections.Generic;
    using BeatEmUp.Characters;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;
    using Microsoft.Xna.Framework.Media;

    /// <summary>
    /// Game Manager class
    /// </summary>
    [Serializable]
    public class GameManager : Microsoft.Xna.Framework.Game
    {
        public GraphicsDeviceManager graphics;
        public static ResolutionManager customResolution 
        {
            private set; 
            get; 
        }
        GameTime gameTime;
        SpriteBatch spriteBatch;
        ScrollingScreen scrollingScreen;
        MenuMainComponent menu;
        EnemiesManager enemies;
        Player player;
        PlayerWeapon playerWeapon;
        PlayersHUD playerHUD;
        WeaponsManager weapons;
        KeyboardState keyboard, keyboardPrevious;
        ScreenFactory worldFactory;
        GameOverScreen gameOver;
        bool isMenuActive = true;
        GameInformation currentGameInfo, loadedGameInfo;
        public List<int> scoresList;
        Stats currentPlayerStats;
        private Texture2D loadingGame;
        string scoresFileName = "savedHighScores.dat";
        private bool beaten;

        /// <summary>
        /// Counstructor
        /// </summary>
        public GameManager()
        {


            this.graphics = new GraphicsDeviceManager(this);
            GameManager.customResolution = new ResolutionManager(this, new Vector2(this.WorldWidth, this.WorldHeight + this.HudHeight));
            SoundManager.SoundManagerInitialize(this);
            this.Content.RootDirectory = "Content";
            this.worldFactory = new ScreenFactory();
            SaveLoadGameManager.SaveLoadManagerInitialize(this);
            currentGameInfo = new GameInformation();
            currentGameInfo.initializeWithZeroParameters();
            loadedGameInfo = new GameInformation();
            loadedGameInfo = null;
            MediaPlayer.IsRepeating = true;
        }

        /// <summary>
        /// Initialization
        /// </summary>
        protected override void Initialize()
        {
            this.menu = new MenuMainComponent(this,isMenuActive);
            base.Initialize();
        }

        /// <summary>
        /// returns SpriteBatch
        /// </summary>
        public SpriteBatch SpriteBatch
        {
            get { return this.spriteBatch; }
        }

        public int WorldWidth
        {
            get
            {
                return 1024;
            }
        }

        public int WorldHeight
        {
            get
            {
                return 768 - HudHeight;
            }
        }

        public int HudHeight
        {
            get
            {
                return PlayersHUD.hudEnd;
            }
        }

        // Used for collisions
        public int HeightFactor
        {
            get
            {
                return 4;
            }
        }

        /// <summary>
        /// Content loading
        /// </summary>
        protected override void LoadContent()
        {   
            scoresList = new List<int>();
            SaveLoadScores.LoadScoresListFromFile(ref scoresFileName, ref scoresList);
            this.spriteBatch = new SpriteBatch(GraphicsDevice);
            LoadObjects();
        }

        /// <summary>
        /// Loading objects
        /// </summary>
        public void LoadObjects()
        {
            UnloadContent();

            SoundManager.LoadContent();
            SoundManager.PlayMenuMusic();

            this.menu.LoadContent(Content);
            menu.scoreList = this.scoresList;
            customResolution.ScaleGameField(GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height);
            this.player = new Player(new Rectangle(0, MovementBoundaries.gameField.Y + (MovementBoundaries.gameField.Height) / 2 - 35, 45, 83),
                Content.Load<Texture2D>(@"Sprites\Player 1\Idle L"), Content.Load<Texture2D>(@"Sprites\Player 1\Idle R"), gameTime);
            this.playerWeapon = new PlayerWeapon(new Vector2(player.GetPosition().X, player.GetPosition().Y), Vector2.Zero, "Sword 2");
            this.playerWeapon.LoadContent(Content);
            this.playerHUD = new HUD.PlayersHUD(1);
            this.playerHUD.LoadContent(Content,GraphicsDevice);
            this.weapons = new WeaponsManager(Content);
            this.enemies = new EnemiesManager(Content);
            this.gameOver = new GameOverScreen(Content);
            CompareWeapons.LoadContent(Content);
            loadingGame = Content.Load<Texture2D>(@"MenuGraphics\LoadingGame");

            Screen screen = this.worldFactory.CreateScreenForLevel(Level.One, this);
            this.scrollingScreen = new ScrollingScreen(this, screen, this.player, this.enemies, this.weapons);
            this.scrollingScreen.LoadContent(Content);
            worldScreen = scrollingScreen.getWorld().worldPos() / WorldWidth;
            oldWorldScreen = scrollingScreen.getWorld().worldPos() / WorldWidth;
            currentPlayerStats = new Stats();
        }

        /// <summary>
        /// Unloading game content
        /// </summary>
        protected override void UnloadContent() { Content.Unload(); }

        /// <summary>
        /// Update game state
        /// </summary>
        /// <param name="gameTime">game time</param>
        protected override void Update(GameTime gameTime)
        {
            this.gameTime = gameTime;
            keyboard = Keyboard.GetState();
            if (!gameOver.IsVisible)
            {
                this.currentGameInfo.playerStats = this.player.getStats();
                this.currentGameInfo.CurrentMap = this.worldScreen;
                this.currentGameInfo.playerPosition = this.player.GetPosition();
                this.currentGameInfo.playerWeapon = this.playerWeapon.Weapon.GetWeaponFullInfo();
                this.currentGameInfo.world = this.scrollingScreen.getWorld().worldPos();

                if (!isMenuActive)
                    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
                        this.Exit();
                menu.MenuEnabled = isMenuActive;

                if (menu.MenuEnabled) menu.Update(gameTime);
                if (menu.areSomeMenuComponentsActive() == false)
                {
                    player.UpdatePosition(Keyboard.GetState(), GamePad.GetState(PlayerIndex.One));

                    enemies.GetCloserToPlayer(player.CollisionRec, player);
                    enemies.Update(gameTime, weapons, playerWeapon.Weapon,player);
                    player.Update(gameTime);
                    this.scrollingScreen.Update(gameTime);
                    playerWeapon.UpdatePosition(new Vector2(player.GetPosition().X, player.GetPosition().Y), player.getFaceDirection(), enemies, player.Attack(), player);
                    weapons.Update(player.CollisionRec, keyboard, keyboardPrevious, playerWeapon);
                    Random r = new Random();
                    if (worldScreen != oldWorldScreen)
                    {
                        oldWorldScreen = worldScreen;
                        if (enemies.EnemiesList.Count < 5)
                        {
                            enemies.GiveMeRandomEnemy(player.GetLevel(), true);
                        }

                    }

                    if (scrollingScreen.ReachedEnd() && enemies.EnemiesList.Count < 1&&pokonany==0)
                    {
                        enemies.GiveMeRandomEnemy(player.GetLevel(), false);
                        pokonany = 1;

                    }
                    else if (scrollingScreen.ReachedEnd() && enemies.EnemiesList.Count==0 && pokonany == 1)
                    {
                        this.scrollingScreen = new ScrollingScreen(this, this.worldFactory.CreateScreenForLevel(Level.Two, this), this.player, this.enemies, this.weapons);
                        pokonany = 0;
                        this.scrollingScreen.LoadContent(Content);
                        worldScreen = 0;
                    }
                    worldScreen = scrollingScreen.getWorld().worldPos() / WorldWidth;
                }
                SaveLoadGameManager.Update(ref this.currentGameInfo, ref this.loadedGameInfo);
                if (loadedGameInfo != null)
                {
                    this.player.setStats(loadedGameInfo.playerStats);
                    this.worldScreen = loadedGameInfo.CurrentMap;
                    this.player.SetPosition(loadedGameInfo.playerPosition);
                    this.playerWeapon.Weapon.SetWeaponFullInfo(this, loadedGameInfo.playerWeapon);

                    this.scrollingScreen = new ScrollingScreen(this, worldFactory.CreateScreenForLevel(Level.One, this, loadedGameInfo.world), this.player, this.enemies, this.weapons);
                    this.scrollingScreen.LoadContent(Content);

                    loadedGameInfo = null;
                }
                SoundManager.Update();

                //SoundManager.StopMusic();
            }
            else
            {
                if (keyboard.IsKeyDown(Keys.Enter)&&keyboardPrevious.IsKeyDown(Keys.Enter))
                {
                    gameOver.IsVisible = false;
                    menu.Initialize();
                    menu.gameWasTurnedOn = false;
                }
            }

            if (player.HP <= 0)
            {
                gameOver.IsVisible = true;
                gameOver.Score = player.getStats().Score;
                
                this.scoresList.Add(gameOver.Score);            
                this.scoresList.Sort();
                this.scoresList.Reverse();
                SaveLoadScores.SaveScoresListToFile(ref scoresFileName, ref scoresList);
                SaveLoadScores.LoadScoresListFromFile(ref scoresFileName, ref scoresList);
                this.menu.scoreList = this.scoresList;
                
                player.HP = 1;
            }

            keyboardPrevious = keyboard;
            
            // Nie usuwac mi tego - V
            //this.Window.Title = "x: " + Mouse.GetState().X.ToString() 
            //    + ", y: " + (Mouse.GetState().Y - this.HudHeight).ToString()
            //    + ", worldHeight-y: " + (this.WorldHeight + this.HudHeight - Mouse.GetState().Y).ToString();

            this.scrollingScreen.Update(gameTime);

            base.Update(gameTime);
        }

        /// <summary>
        /// Draw function
        /// </summary>
        /// <param name="gameTime">game time</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.White);

            spriteBatch.Begin();

            if (gameOver.IsVisible)
                gameOver.Draw(spriteBatch);
            else
            {
                if (menu.areSomeMenuComponentsActive() == false)
                {
                    scrollingScreen.Draw(gameTime);
                    weapons.Draw(spriteBatch);

                    foreach (Enemies enemy in enemies.EnemiesList)
                    {
                        enemy.Draw(spriteBatch);
                    }

                    player.Draw();
                    playerWeapon.Draw(spriteBatch);
                    playerHUD.Draw(spriteBatch, player, playerWeapon.Weapon);

                    if (CompareWeapons.IsVisible)
                        CompareWeapons.Draw(spriteBatch);
                }
                else
                {
                    if (!gameOver.IsVisible)
                        menu.Draw(spriteBatch);
                }

                if (SaveLoadGameManager.isLoadingInProgress)
                {
                    customResolution.Draw(loadingGame, new Rectangle(0, 0, graphics.PreferredBackBufferWidth, graphics.PreferredBackBufferWidth), Color.White);
                    //System.Threading.Thread.Sleep(5000);
                    SaveLoadGameManager.isLoadingInProgress = false;
                }

            }
            spriteBatch.End();
            
            base.Draw(gameTime);
        }

        public int worldScreen { get; set; }

        public int oldWorldScreen { get; set; }

        public int pokonany { get; set; }
    }
}
